package com.huawo.qjs;

import static com.huawo.qjs.utils.QjsUtils.clearDirectory;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Point;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.util.Size;

import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import com.huawo.qjs.callback.QjsWatchfaceCallback;
import com.huawo.qjs.callback.QjsZipCompletedListener;
import com.huawo.qjs.utils.QjsUtils;
import com.huawo.qjs.utils.SFSDK;
import com.huawo.qjs.widgets.QjsDot;
import com.huawo.qjs.widgets.QjsEmpty;
import com.huawo.qjs.widgets.QjsGif;
import com.huawo.qjs.widgets.QjsHourHand;
import com.huawo.qjs.widgets.QjsImage;
import com.huawo.qjs.widgets.QjsMiniteHand;
import com.huawo.qjs.widgets.QjsSecondHand;
import com.huawo.qjs.widgets.QjsTime;
import com.sifli.siflicore.error.SFError;
import com.sifli.siflicore.error.SFErrorCode;
import com.sifli.siflicore.util.ByteUtil;
import com.sifli.watchfacesdk.manager.SFWatchfaceFilePushManagerCallback;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 * 使用demo：
 * // 创建
 * QjsWatchface watchface = new QjsWatchface(this);
 * // 设置样式
 * watchface.setStyle(0);
 * // 设置背景图片 466x466
 * watchface.setBackground(bitmap);
 * // 设置缩略图 264x264
 * watchface.setThumbnail(bitmap);
 * <p>
 * // 设置控件
 * List<QjsWidget> widgets = new ArrayList<>();
 * QjsTime time = new QjsTime("time", 0x00ffff);
 * QjsCalorie cal = new QjsCalorie("cal", 0xff0000);
 * QjsHeartrate hr = new QjsHeartrate("hr", 0xff00ff);
 * QjsStep step = new QjsStep("step", 0xffff00);
 * widgets.add(time);
 * widgets.add(cal);
 * widgets.add(hr);
 * widgets.add(step);
 * <p>
 * // 发送到手表
 * watchface.syncToWatch(bluetoothMacAddress, callback)
 */
public class QjsWatchface {
    private static final String TAG = "QjsWatchface";
    private String name = "diy";
    private int width = 480;
    private int height = 480;
    private int index = 0;
    private Bitmap thumbnail;
    private Bitmap background;
    private String gifFile = "";

    private List<QjsWidget> widgetList;

    private Map<Integer, List<List<Point>>> imgPoints;

    private int style = 0;

    public String getName() {
        return name + index;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public Bitmap getThumbnail() {
        return thumbnail;
    }

    public void setThumbnail(Bitmap thumbnail) {
        this.thumbnail = thumbnail;
    }

    public Bitmap getBackground() {
        return background;
    }

    public void setBackground(Bitmap background) {
        this.background = background;
    }

    public String getGifFile() {
        return gifFile;
    }

    public void setGifFile(String gifFile) {
        this.gifFile = gifFile;
    }

    public List<QjsWidget> getWidgetList() {
        return widgetList;
    }

    public void setWidgetList(List<QjsWidget> widgetList) {

        if (background != null) {
            QjsImage image = new QjsImage("bg");
            image.setLocation(new Point(0, 0));
            image.setSize(new Size(this.width, this.height));
            widgetList.add(0, image);
        }
        if (!gifFile.equals("")) {
            Log.d(TAG, "make: 加载gif");
            QjsGif gif = new QjsGif("gif");
            gif.setLocation(new Point(0, 0));
            gif.setSize(new Size(this.width, this.height));
            widgetList.add(0, gif);
        }
        this.widgetList = widgetList;
        List<QjsWidget> tmpList = new ArrayList<>();
        int handColor = 0xffffff;
        boolean hasHand = false;
        for (int i = 0; i < widgetList.size(); i++) {
            QjsWidget widget = widgetList.get(i);
            widget.setWatchfaceStyle(style);
            if (widget instanceof QjsTime) {
                continue;
            } else if (widget instanceof QjsHourHand) {
                handColor = widget.getColor();
                hasHand = true;
                continue;
            } else if (widget instanceof QjsMiniteHand) {
                handColor = widget.getColor();
                hasHand = true;
                continue;
            } else if (widget instanceof QjsSecondHand) {
                handColor = widget.getColor();
                hasHand = true;
                continue;
            } else if (widget instanceof QjsImage) {
                continue;
            } else if (widget instanceof QjsGif) {
                continue;
            } else if (widget instanceof QjsEmpty) {
//                continue;
            }
            tmpList.add(widget);
        }

        if (hasHand) {
            QjsWidget widget = new QjsDot("dot", handColor);
            if (width == 410) {
                widget.setLocation(new Point(200, 230));
            }else{
                widget.setLocation(new Point(222, 222));
            }

            widgetList.add(widget);
        }

        List<List<Point>> pointList = imgPoints.get(getStyle());
        for (int i = 0; i < tmpList.size(); i++) {
            QjsWidget qjsWidget = tmpList.get(i);
            if (!(qjsWidget instanceof QjsEmpty)) {
                tmpList.get(i).setImgPoint(pointList.get(i).get(qjsWidget.getStyle()));
            }
        }
    }

    public int getStyle() {
        return style;
    }

    /**
     * 设置样式
     *
     * @param style 0 ~ 4
     */
    public void setStyle(int style) {
        this.style = style;
    }

    private Context context;
    private String zipPath;
    private Handler handler;

    public QjsWatchface(Context context, int width, int height, int index) {
        this.context = context;
        this.width = width;
        this.height = height;
        this.index = index;
        handler = new Handler(Looper.getMainLooper());

        // 安装之前 先把里面的内容清了.
        String folderPath = "qjs_temp/dyn/dynamic_app";
        File folder = new File(context.getCacheDir(), folderPath);
        clearDirectory(folder);


        if (width == 466) {


            imgPoints = new HashMap<>();
            List<List<Point>> pointList = new ArrayList<>();
            List<Point> pointList01 = new ArrayList<>();
            pointList01.add(new Point(84, 343));
            pointList01.add(new Point(92, 317));
            pointList01.add(new Point(127, 326));
            pointList01.add(new Point(45, 326));
            List<Point> pointList02 = new ArrayList<>();
            pointList02.add(new Point(357, 343));
            pointList02.add(new Point(357, 317));
            pointList02.add(new Point(370, 326));
            pointList02.add(new Point(306, 326));
            List<Point> pointList03 = new ArrayList<>();
            pointList03.add(new Point(213, 419));
            pointList03.add(new Point(213, 393));
            pointList03.add(new Point(264, 402));
            pointList03.add(new Point(162, 402));
            pointList.add(pointList01);
            pointList.add(pointList02);
            pointList.add(pointList03);
            imgPoints.put(0, pointList);

            pointList = new ArrayList<>();
            List<Point> pointList11 = new ArrayList<>();
            pointList11.add(new Point(148, 64));
            pointList11.add(new Point(148, 38));
            pointList11.add(new Point(156, 46));
            pointList11.add(new Point(94, 46));
            List<Point> pointList12 = new ArrayList<>();
            pointList12.add(new Point(38, 226));
            pointList12.add(new Point(38, 200));
            pointList12.add(new Point(106, 213));
            pointList12.add(new Point(4, 213));
            List<Point> pointList13 = new ArrayList<>();
            pointList13.add(new Point(150, 397));
            pointList13.add(new Point(150, 371));
            pointList13.add(new Point(176, 380));
            pointList13.add(new Point(94, 380));
            pointList.add(pointList11);
            pointList.add(pointList12);
            pointList.add(pointList13);
            imgPoints.put(1, pointList);

            pointList = new ArrayList<>();
            List<Point> pointList21 = new ArrayList<>();
            pointList21.add(new Point(213, 40));
            pointList21.add(new Point(213, 14));
            pointList21.add(new Point(244, 22));
            pointList21.add(new Point(182, 22));
            List<Point> pointList22 = new ArrayList<>();
            pointList22.add(new Point(388, 226));
            pointList22.add(new Point(388, 200));
            pointList22.add(new Point(420, 213));
            pointList22.add(new Point(320, 213));
            List<Point> pointList23 = new ArrayList<>();
            pointList23.add(new Point(213, 416));
            pointList23.add(new Point(213, 390));
            pointList23.add(new Point(254, 402));
            pointList23.add(new Point(172, 402));
            pointList.add(pointList21);
            pointList.add(pointList22);
            pointList.add(pointList23);
            imgPoints.put(2, pointList);

            pointList = new ArrayList<>();
            List<Point> pointList31 = new ArrayList<>();
            pointList31.add(new Point(213, 42));
            pointList31.add(new Point(213, 8));
            pointList31.add(new Point(244, 22));
            pointList31.add(new Point(189, 22));
            List<Point> pointList32 = new ArrayList<>();
            pointList32.add(new Point(118, 166));
            pointList32.add(new Point(118, 140));
            pointList32.add(new Point(170, 156));
            pointList32.add(new Point(48, 156));
            List<Point> pointList33 = new ArrayList<>();
            pointList33.add(new Point(338, 166));
            pointList33.add(new Point(338, 140));
            pointList33.add(new Point(386, 156));
            pointList33.add(new Point(272, 156));
            pointList.add(pointList31);
            pointList.add(pointList32);
            pointList.add(pointList33);
            imgPoints.put(3, pointList);

            pointList = new ArrayList<>();
            List<Point> pointList41 = new ArrayList<>();
            pointList41.add(new Point(213, 40));
            pointList41.add(new Point(213, 15));
            pointList41.add(new Point(254, 22));
            pointList41.add(new Point(172, 22));
            List<Point> pointList42 = new ArrayList<>();
            pointList42.add(new Point(50, 278));
            pointList42.add(new Point(50, 252));
            pointList42.add(new Point(84, 264));
            pointList42.add(new Point(22, 264));
            List<Point> pointList43 = new ArrayList<>();
            pointList43.add(new Point(356, 278));
            pointList43.add(new Point(356, 252));
            pointList43.add(new Point(404, 264));
            pointList43.add(new Point(302, 264));
            pointList.add(pointList41);
            pointList.add(pointList42);
            pointList.add(pointList43);
            imgPoints.put(4, pointList);
        } else if (width == 480) {

            imgPoints = new HashMap<>();
            List<List<Point>> pointList = new ArrayList<>();
            List<Point> pointList01 = new ArrayList<>();
            pointList01.add(new Point(95, 343));
            pointList01.add(new Point(96, 317));
            pointList01.add(new Point(140, 326));
            pointList01.add(new Point(58, 326));
            List<Point> pointList02 = new ArrayList<>();
            pointList02.add(new Point(368, 343));
            pointList02.add(new Point(361, 317));
            pointList02.add(new Point(383, 326));
            pointList02.add(new Point(321, 326));
            List<Point> pointList03 = new ArrayList<>();
            pointList03.add(new Point(220, 419));
            pointList03.add(new Point(213, 393));
            pointList03.add(new Point(264, 402));
            pointList03.add(new Point(162, 402));
            pointList.add(pointList01);
            pointList.add(pointList02);
            pointList.add(pointList03);
            imgPoints.put(0, pointList);

            pointList = new ArrayList<>();
            List<Point> pointList11 = new ArrayList<>();
            pointList11.add(new Point(148, 71));
            pointList11.add(new Point(148, 40));
            pointList11.add(new Point(156, 46));
            pointList11.add(new Point(94, 53));
            List<Point> pointList12 = new ArrayList<>();
            pointList12.add(new Point(38, 233));
            pointList12.add(new Point(38, 207));
            pointList12.add(new Point(106, 213));
            pointList12.add(new Point(4, 220));
            List<Point> pointList13 = new ArrayList<>();
            pointList13.add(new Point(150, 404));
            pointList13.add(new Point(150, 373));
            pointList13.add(new Point(176, 380));
            pointList13.add(new Point(94, 387));
            pointList.add(pointList11);
            pointList.add(pointList12);
            pointList.add(pointList13);
            imgPoints.put(1, pointList);

            pointList = new ArrayList<>();
            List<Point> pointList21 = new ArrayList<>();
            pointList21.add(new Point(220, 47));
            pointList21.add(new Point(220, 19));
            pointList21.add(new Point(251, 22));
            pointList21.add(new Point(189, 22));
            List<Point> pointList22 = new ArrayList<>();
            pointList22.add(new Point(388, 233));
            pointList22.add(new Point(388, 207));
            pointList22.add(new Point(430, 213));
            pointList22.add(new Point(320, 220));
            List<Point> pointList23 = new ArrayList<>();
            pointList23.add(new Point(220, 423));
            pointList23.add(new Point(220, 395));
            pointList23.add(new Point(261, 402));
            pointList23.add(new Point(179, 402));
            pointList.add(pointList21);
            pointList.add(pointList22);
            pointList.add(pointList23);
            imgPoints.put(2, pointList);

            pointList = new ArrayList<>();
            List<Point> pointList31 = new ArrayList<>();
            pointList31.add(new Point(220, 42));
            pointList31.add(new Point(220, 8));
            pointList31.add(new Point(245, 22));
            pointList31.add(new Point(196, 22));
            List<Point> pointList32 = new ArrayList<>();
            pointList32.add(new Point(85, 165));
            pointList32.add(new Point(85, 140));
            pointList32.add(new Point(134, 156));
            pointList32.add(new Point(47, 156));
            List<Point> pointList33 = new ArrayList<>();
            pointList33.add(new Point(345, 165));
            pointList33.add(new Point(345, 140));
            pointList33.add(new Point(389, 156));
            pointList33.add(new Point(291, 156));
            pointList.add(pointList31);
            pointList.add(pointList32);
            pointList.add(pointList33);
            imgPoints.put(3, pointList);

            pointList = new ArrayList<>();
            List<Point> pointList41 = new ArrayList<>();
            pointList41.add(new Point(220, 42));
            pointList41.add(new Point(220, 16));
            pointList41.add(new Point(261, 20));
            pointList41.add(new Point(179, 22));
            List<Point> pointList42 = new ArrayList<>();
            pointList42.add(new Point(57, 278));
            pointList42.add(new Point(57, 252));
            pointList42.add(new Point(91, 264));
            pointList42.add(new Point(29, 264));
            List<Point> pointList43 = new ArrayList<>();
            pointList43.add(new Point(363, 278));
            pointList43.add(new Point(363, 252));
            pointList43.add(new Point(411, 264));
            pointList43.add(new Point(309, 264));
            pointList.add(pointList41);
            pointList.add(pointList42);
            pointList.add(pointList43);
            imgPoints.put(4, pointList);
        } else if (width == 410) {

            imgPoints = new HashMap<>();
            List<List<Point>> pointList = new ArrayList<>();
            List<Point> pointList01 = new ArrayList<>();
            pointList01.add(new Point(60, 351));
            pointList01.add(new Point(68, 325));
            pointList01.add(new Point(104, 338));
            pointList01.add(new Point(22, 338));
            List<Point> pointList02 = new ArrayList<>();
            pointList02.add(new Point(320, 351));
            pointList02.add(new Point(320, 325));
            pointList02.add(new Point(347, 338));
            pointList02.add(new Point(285, 338));
            List<Point> pointList03 = new ArrayList<>();
            pointList03.add(new Point(185, 441));
            pointList03.add(new Point(185, 415));
            pointList03.add(new Point(236, 430));
            pointList03.add(new Point(134, 430));
            pointList.add(pointList01);
            pointList.add(pointList02);
            pointList.add(pointList03);
            imgPoints.put(0, pointList);

            pointList = new ArrayList<>();
            List<Point> pointList11 = new ArrayList<>();
            pointList11.add(new Point(185, 59));
            pointList11.add(new Point(185, 33));
            pointList11.add(new Point(216, 46));
            pointList11.add(new Point(154, 46));
            List<Point> pointList12 = new ArrayList<>();
            pointList12.add(new Point(185, 433));
            pointList12.add(new Point(185, 407));
            pointList12.add(new Point(226, 420));
            pointList12.add(new Point(144, 420));
            pointList.add(pointList11);
            pointList.add(pointList12);
            imgPoints.put(1, pointList);

            pointList = new ArrayList<>();
            List<Point> pointList21 = new ArrayList<>();
            pointList21.add(new Point(254, 49));
            pointList21.add(new Point(254, 23));
            pointList21.add(new Point(285, 36));
            pointList21.add(new Point(285, 36));
            List<Point> pointList22 = new ArrayList<>();
            pointList22.add(new Point(254, 443));
            pointList22.add(new Point(254, 417));
            pointList22.add(new Point(295, 430));
            pointList22.add(new Point(213, 430));
            pointList.add(pointList21);
            pointList.add(pointList22);
            imgPoints.put(2, pointList);

            pointList = new ArrayList<>();
            List<Point> pointList31 = new ArrayList<>();
            pointList31.add(new Point(185, 56));
            pointList31.add(new Point(185, 36));
            pointList31.add(new Point(210, 46));
            pointList31.add(new Point(160, 46));
            List<Point> pointList32 = new ArrayList<>();
            pointList32.add(new Point(74, 165));
            pointList32.add(new Point(74, 139));
            pointList32.add(new Point(115, 152));
            pointList32.add(new Point(33, 152));
            List<Point> pointList33 = new ArrayList<>();
            pointList33.add(new Point(298, 165));
            pointList33.add(new Point(298, 139));
            pointList33.add(new Point(348, 152));
            pointList33.add(new Point(246, 152));
            pointList.add(pointList31);
            pointList.add(pointList32);
            pointList.add(pointList33);
            imgPoints.put(3, pointList);

            pointList = new ArrayList<>();
            List<Point> pointList41 = new ArrayList<>();
            pointList41.add(new Point(185, 42));
            pointList41.add(new Point(185, 18));
            pointList41.add(new Point(226, 30));
            pointList41.add(new Point(144, 30));
            List<Point> pointList42 = new ArrayList<>();
            pointList42.add(new Point(46, 252));
            pointList42.add(new Point(46, 226));
            pointList42.add(new Point(78, 238));
            pointList42.add(new Point(16, 238));
            List<Point> pointList43 = new ArrayList<>();
            pointList43.add(new Point(304, 252));
            pointList43.add(new Point(304, 226));
            pointList43.add(new Point(354, 238));
            pointList43.add(new Point(252, 238));
            pointList.add(pointList41);
            pointList.add(pointList42);
            pointList.add(pointList43);
            imgPoints.put(4, pointList);
        }
    }

    public QjsWatchface() {

    }

    private String localZipPath;

    public QjsWatchface(String zipPath, Context context) {
        this.localZipPath = zipPath;
        this.context = context;
    }

    private void cleanUp() {
        callback = null;
//        LocalBroadcastManager.getInstance(this.context).unregisterReceiver(this.syncReceiver);
    }

    int previousProgress = 0;

    public void syncOnlineZip(String bluetoothAddress, QjsWatchfaceCallback callback) {
        this.callback = callback;
        //旧版本
//        IntentFilter intentFilter = new IntentFilter();
//        intentFilter.addAction(SifliWatchfaceService.BROADCAST_WATCHFACE_STATE);
//        intentFilter.addAction(SifliWatchfaceService.BROADCAST_WATCHFACE_PROGRESS);
//        LocalBroadcastManager.getInstance(this.context).registerReceiver(this.syncReceiver, intentFilter);
//        SifliWatchfaceService.startActionWatchface(context, this.localZipPath, bluetoothAddress, 5, 0);
        //新版本
        SFSDK.getInstance().pushWatchface(bluetoothAddress, 5, this.localZipPath, false, new SFWatchfaceFilePushManagerCallback() {

            @Override
            public void onManagerStatusChanged(int status) {
                /**
                 * 0为空闲，1，连接中，2工作中
                 */
                Log.i(TAG, "manager====status===" + status);
            }

            @Override
            public void onProgress(long currentBytes, long totalBytes) {
                int progress = 0;
                if (totalBytes > 0) {
                    double percent = (double) currentBytes / totalBytes;
                    progress = (int) (percent * 100);
                }
                if (progress == previousProgress) {

                } else {
                    previousProgress = progress;
                    callback.onProccess(progress);
                }
            }

            @Override
            public void onComplete(boolean success, SFError error) {
                Log.i(TAG, "QjsWatchface==manager====success===" + success + "==error==" + error);

                if (lastExecutionTime != 0  && System.currentTimeMillis() - lastExecutionTime  <= 1000){//SDK 同时回调了2个结果 , 过滤
                    return;
                }
                lastExecutionTime = System.currentTimeMillis();

                if (success) {
                    if (handler == null) {
                        handler = new Handler(Looper.getMainLooper());
                    }
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            callback.onSuccess();
                            cleanUp();
                        }
                    }, 500);
                } else {
                    if (error != null) {
                        int deviceErrorCode = error.getDeviceErrorCode();
                        int code = error.getCode();
                        if (code == SFErrorCode.SF_DEVICE_ERROR_CODE) {
                            deviceErrorCode = translateCode(deviceErrorCode);
                            Log.i(TAG, "QjsWatchface==manager====deviceErrorCode===" + deviceErrorCode);
                            callback.onFail(deviceErrorCode);
                            cleanUp();
                        } else {
                            code = translateCode(code);
                            Log.i(TAG, "QjsWatchface==manager====code===" + code);
                            callback.onFail(code);
                            cleanUp();
                        }
                    }
                }
                SFSDK.getInstance().cleanUp();
            }
        });
    }

    private int translateCode(int code) {
        byte[] bytes = ByteUtil.intTo2Bytes(code);
        if ((bytes[1] & 0b10000000) > 0) {
            code = (code & 0x7fff);
        }
        return code;
    }

    private QjsWatchfaceCallback callback;

    private long lastExecutionTime = 0;

    public void syncToWatch(String bluetoothAddress, QjsWatchfaceCallback callback) {
        if (callback == null) return;
        this.callback = callback;

        Context context = this.context;
        final QjsWatchface self = this;
        // 生成zip
        QjsZipTask task = new QjsZipTask(this, handler, new QjsZipCompletedListener() {
            @Override
            public void onCompleted() {
                String path = self.zipPath;
                Log.i(TAG, "qjs zip onCompleted: " + path);
                if (self.callback != null) {
                    self.callback.onReady();
                    SFSDK.getInstance().pushWatchface(bluetoothAddress, 5, path, true, new SFWatchfaceFilePushManagerCallback() {

                        @Override
                        public void onManagerStatusChanged(int status) {
                            /**
                             * 0为空闲，1，连接中，2工作中
                             */
                            Log.i(TAG, "manager====status===" + status);
                        }

                        @Override
                        public void onProgress(long currentBytes, long totalBytes) {
                            int progress = 0;
                            if (totalBytes > 0) {
                                double percent = (double) currentBytes / totalBytes;
                                progress = (int) (percent * 100);
                            }
                            if (progress == previousProgress) {

                            } else {
                                previousProgress = progress;
                                callback.onProccess(progress);
                            }
                        }

                        @Override
                        public void onComplete(boolean success, SFError error) {
                            Log.i(TAG, "QjsWatchface==manager====success===" + success + "==error==" + error);

                            if (lastExecutionTime != 0  && System.currentTimeMillis() - lastExecutionTime <=  1000){//SDK 同时回调了2个结果 , 过滤
                                return;
                            }
                            lastExecutionTime = System.currentTimeMillis();
                            
                            if (success) {
                                if (handler == null) {
                                    handler = new Handler(Looper.getMainLooper());
                                }
                                handler.postDelayed(new Runnable() {
                                    @Override
                                    public void run() {
                                        callback.onSuccess();
                                        cleanUp();
                                    }
                                }, 500);
                            } else {
                                if (error != null) {
                                    int deviceErrorCode = error.getDeviceErrorCode();
                                    int code = error.getCode();
                                    if (code == SFErrorCode.SF_DEVICE_ERROR_CODE) {
                                        deviceErrorCode = translateCode(deviceErrorCode);
                                        Log.i(TAG, "QjsWatchface==manager====deviceErrorCode===" + deviceErrorCode);
                                        callback.onFail(deviceErrorCode);
                                        cleanUp();
                                    } else {
                                        code = translateCode(code);
                                        Log.i(TAG, "QjsWatchface==manager====code===" + code);
                                        callback.onFail(code);
                                        cleanUp();
                                    }
                                }
                            }
                            SFSDK.getInstance().cleanUp();
                        }
                    });
                }

            }
        });
        if (self.callback != null) {
            task.execute();
        }

    }
//
//    private final BroadcastReceiver syncReceiver = new BroadcastReceiver() {
//        @Override
//        public void onReceive(Context context, Intent intent) {
//            String action = intent.getAction();
//            if (action.equalsIgnoreCase(SifliWatchfaceService.BROADCAST_WATCHFACE_STATE)) {
//                int state = intent.getIntExtra(SifliWatchfaceService.EXTRA_WATCHFACE_STATE, -1);
//                int code = intent.getIntExtra(SifliWatchfaceService.EXTRA_WATCHFACE_STATE_RSP, 0);
//                Log.i(TAG, "onReceive state:=====" + state + "===== code =====" + code);
//                if (code < 0) {
//                    int result = 65536 + code;
//                    if (result >= 32768) {
//                        code = result - 32768;
//                    }
//                }
//                if (state != 0) {
//                    callback.onFail(code);
//                    cleanUp();
//                } else {
//                    if (handler == null) {
//                        handler = new Handler(Looper.getMainLooper());
//                    }
//                    handler.postDelayed(new Runnable() {
//                        @Override
//                        public void run() {
//                            callback.onSuccess();
//                            cleanUp();
//                        }
//                    }, 500);
//                }
//                Log.i(TAG, "onReceive code:=====" + code);
//            } else if (action.equalsIgnoreCase(SifliWatchfaceService.BROADCAST_WATCHFACE_PROGRESS)) {
//                int progress = intent.getIntExtra(SifliWatchfaceService.EXTRA_WATCHFACE_PROGRESS, 0);
//                callback.onProccess(progress);
//            }
//        }
//    };

    public void make() {
        // 创建相关目录
        Log.i(TAG, "make: 创建相关目录");
        QjsUtils.createQjsTmpDir(getName(), this.context);

        if (thumbnail != null) {
            QjsUtils.exportBin(thumbnail, 0xffffff, false, false, "thumb.bin", getName(), this.context);
        }
        if (!gifFile.equals("")) {
            try {
                //设置获取gif第一帧
                QjsUtils.exportBin(background, 0xffffff, false, false, "gif_ff.bin", getName(), this.context);

                //byte  转agif
                byte[] bytes = QjsUtils.convertFileToByteArray(gifFile.toString());
                QjsUtils.exportBin(bytes, 0xffffff, false, false, "gif.agif", getName(), this.context);
                AssetManager assetManager = this.context.getAssets();
                try {
                    String watchPng = "watch_icon_kong_black.png";
                    if (getWidth() == 480) {
                        watchPng = "watch_icon_kong_black_480.png";
                    } else if (getWidth() == 410) {
                        watchPng = "watch_icon_kong.png";
                    }
                    InputStream inputStream = assetManager.open(watchPng);
                    Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                    if (bitmap != null) {
                        //盖一层透明空心圆，黑色背景的图片
                        QjsUtils.exportBin(bitmap, 0xffffff, false, false, "bg.bin", getName(), this.context);
                    }
                    // 在此处使用bitmap对象进行处理或显示
                } catch (IOException e) {
                    e.printStackTrace();
                }


            } catch (IOException e) {
                Log.i(TAG, "make: GIF压缩异常");
                throw new RuntimeException(e);
            }
        } else {
            if (background != null) {
                Log.e("caixin", background.toString());
                QjsUtils.exportBin(background, 0xffffff, false, false, "bg.bin", getName(), this.context);
            }
        }

        List<QjsResource> noezipResourceList = new ArrayList<>();
        List<QjsResource> resourceList = new ArrayList<>();

        List<QjsResource> noezipAodResourceList = new ArrayList<>();
        List<QjsResource> aodResourceList = new ArrayList<>();
        List<QjsWidget> list = getWidgetList();
        for (int i = 0; i < list.size(); i++) {
            QjsWidget widget = list.get(i);
            boolean shouldEZip = true;
            if ((widget instanceof QjsHourHand)
                    || (widget instanceof QjsMiniteHand)
                    || (widget instanceof QjsSecondHand)) {
                shouldEZip = false;
            }

            for (int j = 0; j < widget.getImageNames().size(); j++) {
                String imgName = widget.getImageNames().get(j);
                QjsResource res = new QjsResource(imgName, widget.getColor());
                if (shouldEZip) {
                    resourceList.add(res);
                    if (!(widget instanceof QjsImage)) {
                        aodResourceList.add(res);
                    }
                } else {
                    noezipResourceList.add(res);
                    noezipAodResourceList.add(res);
                }
            }

        }

        List<QjsResource> noRepeatList = new ArrayList<>();
        Map<String, QjsResource> map = new HashMap<>();
        for (int i = 0; i < resourceList.size(); i++) {
            QjsResource resource = resourceList.get(i);
            if (!map.containsKey(resource.getKey())) {
                map.put(resource.getKey(), resource);
                noRepeatList.add(resource);
            }
        }

        // 保存图片bin
        for (int i = 0; i < noRepeatList.size(); i++) {
            QjsResource resource = noRepeatList.get(i);
            String tmpId = resource.getId();
            if (tmpId.endsWith("_g")) {
                tmpId = tmpId.replace("_g", "");
            }

            AssetManager assetManager = this.context.getAssets();
            try {
                Log.e("caixin", tmpId + ".png");
                InputStream inputStream = assetManager.open(tmpId + ".png");
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                QjsUtils.exportBin(bitmap, resource.getColor(), false, false, resource.getKey() + ".bin", getName(), this.context);
                // 在此处使用bitmap对象进行处理或显示
            } catch (IOException e) {
                e.printStackTrace();
                Log.e("caixin", tmpId + ".png");
            }
        }

        List<QjsResource> aodNoRepeatList = new ArrayList<>();
        Map<String, QjsResource> aodMap = new HashMap<>();
        for (int i = 0; i < aodResourceList.size(); i++) {
            QjsResource resource = aodResourceList.get(i);
            if (!aodMap.containsKey(resource.getKey())) {
                aodMap.put(resource.getKey(), resource);
                aodNoRepeatList.add(resource);
            }
        }

        // 保存图片bin
        for (int i = 0; i < aodNoRepeatList.size(); i++) {
            QjsResource resource = aodNoRepeatList.get(i);
            String tmpId = resource.getId();
            if (tmpId.endsWith("_g")) {
                tmpId = tmpId.replace("_g", "");
            }
            AssetManager assetManager = this.context.getAssets();
            try {
                InputStream inputStream = assetManager.open(tmpId + ".png");
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                QjsUtils.exportBin(bitmap, resource.getColor(), true, false, resource.getKey() + ".bin", getName(), this.context);
                // 在此处使用bitmap对象进行处理或显示
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        // 保存不需要压缩的图片
        List<QjsResource> noezipNoRepeatList = new ArrayList<>();
        Map<String, QjsResource> nozipMap = new HashMap<>();
        for (int i = 0; i < noezipResourceList.size(); i++) {
            QjsResource resource = noezipResourceList.get(i);
            if (!nozipMap.containsKey(resource.getKey())) {
                nozipMap.put(resource.getKey(), resource);
                noezipNoRepeatList.add(resource);
            }
        }

        // 保存图片bin
        for (int i = 0; i < noezipNoRepeatList.size(); i++) {
            QjsResource resource = noezipNoRepeatList.get(i);
            String tmpId = resource.getId();
            if (tmpId.endsWith("_g")) {
                tmpId = tmpId.replace("_g", "");
            }
            AssetManager assetManager = this.context.getAssets();
            try {
                InputStream inputStream = assetManager.open(tmpId + ".png");
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                QjsUtils.exportBin(bitmap, resource.getColor(), false, true, resource.getKey() + ".bin", getName(), this.context);
                // 在此处使用bitmap对象进行处理或显示
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        List<QjsResource> noezipAodNoRepeatList = new ArrayList<>();
        Map<String, QjsResource> noezipAodMap = new HashMap<>();
        for (int i = 0; i < noezipAodResourceList.size(); i++) {
            QjsResource resource = noezipAodResourceList.get(i);
            if (!noezipAodMap.containsKey(resource.getKey())) {
                noezipAodMap.put(resource.getKey(), resource);
                noezipAodNoRepeatList.add(resource);
            }
        }

        for (int i = 0; i < noezipAodNoRepeatList.size(); i++) {
            QjsResource resource = noezipAodNoRepeatList.get(i);
            String tmpId = resource.getId();
            if (tmpId.endsWith("_g")) {
                tmpId = tmpId.replace("_g", "");
            }
            AssetManager assetManager = this.context.getAssets();
            try {
                InputStream inputStream = assetManager.open(tmpId + ".png");
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                QjsUtils.exportBin(bitmap, resource.getColor(), true, true, resource.getKey() + ".bin", getName(), this.context);
                // 在此处使用bitmap对象进行处理或显示
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        // new main.js
        Log.i(TAG, "make: 生成main.js");
        String jwMainJS = generateMainJS(false);
        // AOD 移除掉背景图片
        String aodMainJS = generateMainJS(true);

        Log.i(TAG, "make: 保存main.js");
        QjsUtils.writeMainJS(jwMainJS, false, getName(), this.context);
        QjsUtils.writeMainJS(aodMainJS, true, getName(), this.context);

        // package zip
        String zipPath = QjsUtils.packageQjs(getName(), this.context);
        if (zipPath == null) {
            Log.e(TAG, "打包zip失败，请排查问题");
        }
        this.zipPath = zipPath;
    }

    private String generateMainJS(boolean isAOD) {
        // new main.js
        String prefix = isAOD ? "AOD_" : "JW_";
        int type = isAOD ? 0 : 1;
        StringBuilder sb = new StringBuilder();
        // 先加依赖
        Map<String, QjsDependence> dependenceMap = new HashMap<>();
        List<QjsDependence> dependenceList = new ArrayList<>();
        dependenceList.addAll(QjsDependence.baseDependences());
        for (int i = 0; i < getWidgetList().size(); i++) {
            QjsWidget widget = getWidgetList().get(i);
            for (int j = 0; j < widget.getDependences().size(); j++) {
                QjsDependence dependence = widget.getDependences().get(j);
                if (dependenceMap.containsKey(dependence.getModule())) {
                    continue;
                }
                dependenceMap.put(dependence.getModule(), dependence);
                dependenceList.add(dependence);
            }
        }
        for (int i = 0; i < dependenceList.size(); i++) {
            QjsDependence dependence = dependenceList.get(i);
            sb.append(dependence.toQjs() + "\n");
        }

        sb.append("\nclass " + prefix + getName() + " extends app {\n");
        sb.append("\tconstructor() {\n");
        sb.append(String.format(Locale.ENGLISH,"\t\tsuper(%d);\n", type));
        sb.append("\t}\n");
        // start
        sb.append("\tstart() {\n");
        for (int i = 0; i < widgetList.size(); i++) {
            QjsWidget widget = widgetList.get(i);
            // AOD要移除掉背景图片
            if (widget instanceof QjsImage) {
                if (isAOD) continue;
            }
            // AOD要移除掉GIF
            if (widget instanceof QjsGif) {
                if (isAOD) continue;
            }
            widget.index = i;
            sb.append(widget.start());
        }
        // Add useless data
        sb.append("\tlet __reserve = 0;\n");

        sb.append("\t}\n");

        //resume、pause、stop
        generateLifecycleJS(sb, isAOD);

        sb.append("}\n");
        sb.append(String.format(Locale.ENGLISH,"globalThis.%s%s = %s%s;", prefix, getName(), prefix, getName()));
        return sb.toString();
    }

    /**
     * @param sbALL
     * @param isAOD
     */
    public StringBuilder generateLifecycleJS(StringBuilder sbALL, boolean isAOD) {
        StringBuilder sbContent = new StringBuilder();//  resume
        StringBuilder sbPause = new StringBuilder();//  pause
        sbPause.append("\t\tthis.task();\n");
        StringBuilder sbStop = new StringBuilder();//  stop

        for (int i = 0; i < widgetList.size(); i++) {
            QjsWidget widget = widgetList.get(i);
            // AOD要移除掉背景图片
            if (widget instanceof QjsImage) {
                if (isAOD) continue;
            }
            // AOD要移除掉gif
            if (widget instanceof QjsGif) {
                if (isAOD) continue;
            }
            widget.index = i;
            //resume
            sbContent.append(widget.Resume());
            //pause
            sbPause.append(widget.pause());
            //stop
            sbStop.append(widget.stop());
        }

        //resume
        if (sbContent.length() > 0
                && !"null".equals(sbContent.toString())
                && !"".equals(sbContent.toString())) {
            sbALL.append("\tresume() {\n");
            sbALL.append(sbContent);
            sbALL.append("\t}\n");
        }
        //pause
        if (sbPause.length() > 0
                && !"null".equals(sbPause.toString())
                && !"".equals(sbPause.toString())) {
            sbALL.append("\tpause() {\n");
//            sbALL.append("\t\tthis.task();\n");
            sbALL.append(sbPause);
            sbALL.append("\t}\n");
        }
        //stop
        if (sbStop.length() > 0
                && !"null".equals(sbStop.toString())
                && !"".equals(sbStop.toString())) {
            sbALL.append("\tstop() {\n");
            sbALL.append(sbStop);
            sbALL.append("\t}\n");
        }
        return sbALL;
    }
}
